package com.ym521.facecheck.core

import android.annotation.SuppressLint
import android.graphics.Bitmap
import androidx.camera.core.ImageProxy
import com.ym521.facecheck.bean.ImageBitmap
import com.ym521.facecheck.bean.ImageHandlerType
import com.ym521.facecheck.utils.ImagePool
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.cancel
import kotlinx.coroutines.launch
import java.util.concurrent.LinkedBlockingQueue

/**
 *@author Ym
 *E-mail: 2435970206@qq.com
 *createTime:2024/6/30
 *explain:
 *
 */
internal class ImageQueueEngine private constructor() : IImageQueueEngine {

    private lateinit var faceImageQueue: LinkedBlockingQueue<ImageBitmap>
    private var faceChackScope: CoroutineScope? = null
    private var faceCheck: IFaceCheck? = null

    companion object {
        private const val QUEUE_MAX_SIZE = 8
        fun build(): IImageQueueEngine {
            return ImageQueueEngine()
        }
    }

    override fun initQueueEngine(faceCheck: IFaceCheck): IImageQueueEngine {
        faceImageQueue = LinkedBlockingQueue<ImageBitmap>(QUEUE_MAX_SIZE)
        this.faceCheck = faceCheck
        return this
    }


    override fun putImage(image: Bitmap) {
        if (faceImageQueue.size < QUEUE_MAX_SIZE) {
            val imageBitmap = convertImage(image)
            faceImageQueue.offer(imageBitmap)
        }
    }


    override fun putImage(image: ImageProxy) {
        if (faceImageQueue.size < QUEUE_MAX_SIZE) {
            val imageBitmap = convertImage(image)
            imageBitmap?.let {
                faceImageQueue.offer(imageBitmap)
            }
        }
    }

    /**
     * 开始运行检测
     */
    override fun startRunning(type: ImageHandlerType): IImageQueueEngine {
        faceChackScope = CoroutineScope(Dispatchers.IO)
        faceChackScope?.launch(Dispatchers.Default) {
            while (true) {
                val intBitmap = faceImageQueue.take()
                ImagePool.releaseImage(intBitmap)
                when (type) {
                    ImageHandlerType.IMAGE_HANDLER_2 -> faceCheck?.faceCheckFromRgba2(intBitmap)
                    ImageHandlerType.IMAGE_HANDLER_1 -> faceCheck?.faceCheckFromRgba(intBitmap)
                }
            }
        }
        return this
    }

    override fun release() {
        faceChackScope?.cancel()
        faceChackScope = null
        if (this::faceImageQueue.isInitialized)
            faceImageQueue.forEach {
                it?.bitmap?.recycle()
            }
    }


    /**
     * imageProxy -> RGBA
     */
    @SuppressLint("UnsafeOptInUsageError")
    private fun convertImage(imageProxy: ImageProxy): ImageBitmap? {
        val image = imageProxy.image ?: return null
        val planes = image.planes
        val buffer = planes[0].buffer
        val pixelStride = planes[0].pixelStride
        val rowStride = planes[0].rowStride
        val rowPadding = rowStride - pixelStride * image.width
        val bitmapWidth = image.width
        val bitmapHeight = image.height - rowPadding / pixelStride
        val imageBitmap =
            ImagePool.applyImage(bitmapWidth, bitmapHeight, Bitmap.Config.ARGB_8888)
        imageBitmap.bitmap.copyPixelsFromBuffer(buffer)
        return imageBitmap
    }

    /**
     * imageProxy -> RGBA
     */
    private fun convertImage(bitmap: Bitmap): ImageBitmap {

        return ImagePool.applyImage(bitmap)
    }


}